﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Db4objects.Db4o;
using Db4objects.Db4o.Linq;
using Domain; 

namespace DAO
{
    public static class EmpresaDAO
    {
        public static Empresa Traer(long username)
        {
            using (IObjectContainer db = Connect.getDataBase())
            {
                try
                {
                    Empresa e = new Empresa();
                    e.UserName = username;

                    IObjectSet empr = db.QueryByExample(e);

                    if (!empr.HasNext())
                        return null;

                    e = (Empresa)empr.Next();
                    Connect.assignId(db, (object)e);
                    return e;
                }
                finally
                {
                    db.Close();
                }
            }    
        }

        public static List<Empresa> Traer(long? username, string razonsocial, string rubro)
        {
            razonsocial = razonsocial == null?null:razonsocial.ToUpper();
            rubro = rubro == null ? null : rubro.ToUpper();

            using (IObjectContainer db = Connect.getDataBase())
            {
                try
                {
                    List<Empresa> lst = (from Empresa e in db
                                         where
                                         (string.IsNullOrEmpty(razonsocial) || e.RazonSocial.ToUpper().Contains(razonsocial)) &&
                                         (string.IsNullOrEmpty(rubro) || e.Rubro.ToUpper().Contains(rubro))
                                         select e).ToList<Empresa>();

                    Connect.lstAssignId(db, lst.AsQueryable().OfType<object>().ToList());
                    return lst;

                }
                finally
                {
                    db.Close();
                }
            }
        }

        public static bool Guardar(Empresa empresa)
        {
            using (IObjectContainer db = Connect.getDataBase())
            {
                try
                {
                    if (empresa.db4oid.HasValue)
                    {
                        Connect.rebindId(db, (object)empresa);
                    }
                    else
                    {
                        Email.Send("Felicitaciones, a partir de este momento formás parte de Hidden Code 2.0, la mejor red de descuentos, beneficios e información de la región. <br /> Gracias por utilizar nuestros servicios.", empresa.EMail, "¡Bienvenido a Hidden Code 2.0!");
                    }


                    db.Store(empresa);
                    db.Commit();
                }
                finally
                {
                    db.Close();
                }
            }
            return true;
        }

        public static bool GetStatisticsAsociaciones(long idempresa, 
                                                    out long asociaciones_semana, out Dictionary<string,long> asociaciones_semana_drill,
                                                    out long asociaciones_mes, out Dictionary<string, long> asociaciones_mes_drill,
                                                    out long asociaciones_anio, out Dictionary<string, long> asociaciones_anio_drill,
                                                    out long asociaciones_total, out Dictionary<string, long> asociaciones_total_drill,
                                                    out long desasociaciones_semana, out Dictionary<string,long> desasociaciones_semana_drill,
                                                    out long desasociaciones_mes, out Dictionary<string, long> desasociaciones_mes_drill,
                                                    out long desasociaciones_anio, out Dictionary<string, long> desasociaciones_anio_drill,
                                                    out long desasociaciones_total, out Dictionary<string,long> desasociaciones_total_drill)
        {
            asociaciones_semana = 0;
            asociaciones_semana_drill = new Dictionary<string, long>();
            asociaciones_mes = 0;
            asociaciones_mes_drill = new Dictionary<string, long>();
            asociaciones_anio = 0;
            asociaciones_anio_drill = new Dictionary<string, long>();
            asociaciones_total = 0;
            asociaciones_total_drill = new Dictionary<string, long>();
            desasociaciones_semana = 0;
            desasociaciones_semana_drill = new Dictionary<string, long>();
            desasociaciones_mes = 0;
            desasociaciones_mes_drill = new Dictionary<string, long>();
            desasociaciones_anio = 0;
            desasociaciones_anio_drill = new Dictionary<string, long>();
            desasociaciones_total = 0;
            desasociaciones_total_drill = new Dictionary<string, long>();

            using (IObjectContainer db = Connect.getDataBase())
            {
                try
                {
                    Empresa emp = (from Empresa e in db
                                   where e.UserName == idempresa
                                   select e).First();

                    List<long> lstPublicaciones = (from p in emp.Publicaciones
                                                   select p.Id).ToList();

                    var asociaciones = (from Usuario u in db
                                      from a in u.AsociacionesActivas
                                      where (a.IdEmpresa.HasValue && a.IdEmpresa==idempresa) ||
                                            (a.IdPublicidad.HasValue && lstPublicaciones.Contains(a.IdPublicidad.Value))
                                       select new { 
                                                    item = a.IdEmpresa.HasValue ? "Empresa" : emp.Publicaciones.Find(delegate(Publicacion p) { return p.Id == a.IdPublicidad.Value;  }).Descripcion.ToString(),
                                                    semana =  (a.FechaAsociacion >= DateTime.Today.AddDays(-7).Date ?  1 : 0),
                                                    mes = (a.FechaAsociacion >= DateTime.Today.AddMonths(-1).Date ? 1 : 0),
                                                    anio = (a.FechaAsociacion >= DateTime.Today.AddYears(-1).Date ? 1 : 0),
                                                    total = 1
                                       });

                    foreach (var a in asociaciones)
                    {
                        asociaciones_semana += a.semana;
                        asociaciones_mes += a.mes;
                        asociaciones_anio += a.anio;
                        asociaciones_total += a.total;
                        if (a.semana > 0 )
                        {
                            if (!asociaciones_semana_drill.ContainsKey(a.item))
                                asociaciones_semana_drill.Add(a.item, a.semana);
                            else
                                asociaciones_semana_drill[a.item] += a.semana;
                        }

                        if (a.mes > 0)
                        {
                            if (!asociaciones_mes_drill.ContainsKey(a.item))
                                asociaciones_mes_drill.Add(a.item, a.mes);
                            else
                                asociaciones_mes_drill[a.item] += a.mes;
                        }

                        if (a.anio > 0)
                        {
                            if (!asociaciones_anio_drill.ContainsKey(a.item))
                                asociaciones_anio_drill.Add(a.item, a.anio);
                            else
                                asociaciones_anio_drill[a.item] += a.anio;
                        }

                        if (a.total > 0)
                        {
                            if (!asociaciones_total_drill.ContainsKey(a.item))
                                asociaciones_total_drill.Add(a.item, a.total);
                            else
                                asociaciones_total_drill[a.item] += a.total;
                        }

                    }

                    var desasociaciones = (from Usuario u in db
                                        from a in u.Asociaciones
                                           where !u.AsociacionesActivas.Contains(a) && 
                                              ((a.IdEmpresa.HasValue && a.IdEmpresa == idempresa) ||
                                              (a.IdPublicidad.HasValue && lstPublicaciones.Contains(a.IdPublicidad.Value)))
                                        select new
                                        {
                                            item = a.IdEmpresa.HasValue ? "Empresa" : emp.Publicaciones.Find(delegate(Publicacion p) { return p.Id == a.IdPublicidad.Value; }).Descripcion.ToString(),
                                            semana = (a.FechaAsociacion >= DateTime.Today.AddDays(-7).Date ? 1 : 0),
                                            mes = (a.FechaAsociacion >= DateTime.Today.AddMonths(-1).Date ? 1 : 0),
                                            anio = (a.FechaAsociacion >= DateTime.Today.AddYears(-1).Date ? 1 : 0),
                                            total = 1
                                        });

                    foreach (var a in desasociaciones)
                    {
                        desasociaciones_semana += a.semana;
                        desasociaciones_mes += a.mes;
                        desasociaciones_anio += a.anio;
                        desasociaciones_total += a.total;
                        if (a.semana > 0)
                        {
                            if (!desasociaciones_semana_drill.ContainsKey(a.item))
                                desasociaciones_semana_drill.Add(a.item, a.semana);
                            else
                                desasociaciones_semana_drill[a.item] += a.semana;
                        }

                        if (a.mes > 0)
                        {
                            if (!desasociaciones_mes_drill.ContainsKey(a.item))
                                desasociaciones_mes_drill.Add(a.item, a.mes);
                            else
                                desasociaciones_mes_drill[a.item] += a.mes;
                        }

                        if (a.anio > 0)
                        {
                            if (!desasociaciones_anio_drill.ContainsKey(a.item))
                                desasociaciones_anio_drill.Add(a.item, a.anio);
                            else
                                desasociaciones_anio_drill[a.item] += a.anio;
                        }

                        if (a.total > 0)
                        {
                            if (!desasociaciones_total_drill.ContainsKey(a.item))
                                desasociaciones_total_drill.Add(a.item, a.total);
                            else
                                desasociaciones_total_drill[a.item] += a.total;
                        }

                    }

                    return true;


                }
                finally
                {
                    db.Close();
                }
            }

            
        }

        public static bool GetStatisticsPublicaciones(long idempresa,
                                                    out Dictionary<string, long> uso_publicaciones,
                                                    out Dictionary<string, long> seguimiento_publicaciones)
        {
            uso_publicaciones = new Dictionary<string,long>();
            seguimiento_publicaciones = new Dictionary<string, long>();

            using (IObjectContainer db = Connect.getDataBase())
            {
                try
                {
                    Empresa emp = (from Empresa e in db
                                   where e.UserName == idempresa
                                   select e).First();

                    List<long> lstPublicaciones = (from p in emp.Publicaciones
                                                   select p.Id).ToList();


                    var usos = from Usuario u in db
                              from c in u.Consumos
                              where lstPublicaciones.Contains(c.IdPublicidad)
                               select new { id = emp.Publicaciones.Find(delegate(Publicacion p) { return p.Id == c.IdPublicidad; }).Descripcion.ToString() };

                    var usosAgrupados = usos.GroupBy(uso => uso.id).Select(lst => new { id = lst.Key.ToString(), cuenta = lst.Count() });

                    foreach (var u in usosAgrupados)
                    {
                        if (!uso_publicaciones.ContainsKey(u.id))
                            uso_publicaciones.Add(u.id, u.cuenta);
                        else
                            uso_publicaciones[u.id] += u.cuenta;
                    }

                    var seguimiento = (from Usuario u in db
                                      from Asociacion a in u.AsociacionesActivas
                                      where (a.IdPublicidad.HasValue && lstPublicaciones.Contains(a.IdPublicidad.Value))
                                       select new { id = emp.Publicaciones.Find(delegate(Publicacion p) { return p.Id == a.IdPublicidad.Value;  }).Descripcion.ToString(), 
                                                    cuenta = 1 });

                    foreach (var s in seguimiento)
                    {
                        if (!seguimiento_publicaciones.ContainsKey(s.id))
                            seguimiento_publicaciones.Add(s.id, s.cuenta);
                        else
                            seguimiento_publicaciones[s.id] += s.cuenta;
                    }
                    
                    return true;


                }
                finally
                {
                    db.Close();
                }
            }


        }
    }
}
